home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Documentation / Tech Notes & Articles / Recipes / Part Persistency / Multiple Kind Support Recipe < prev    next >
Encoding:
Text File  |  1995-11-07  |  14.2 KB  |  127 lines  |  [TEXT/ttxt]

  1. OpenDoc™ Recipes
  2.  
  3.  
  4. Multiple Kind Support Recipe
  5. By The OpenDoc Design Team
  6. November 7th, 1995
  7.  
  8.  
  9. © 1993-1995  Apple Computer, Inc. All Rights Reserved.
  10. Apple, the Apple logo, and Macintosh are registered trademarks of Apple Computer, Inc.
  11. Mac and OpenDoc are trademarks of Apple Computer, Inc. 
  12.  
  13.  
  14.  
  15.  
  16. Introduction
  17.  
  18. OpenDoc provides a structured storage model which enables part editors to persistently store multiple representations of their content.  In order to present this feature in a simple and easy to use manner to users, part editors must follow a few rules in general, and be more particular in their implementation of a handful of their methods.   This document contains the list of part editor responsibilities, and sample code which would allow a part editor to fulfill these responsibilities. 
  19.  
  20.  
  21. Terminology
  22.  
  23. •    Kind = specific Data Format orType
  24. • Category = set of similar Kinds.  A Kind can be in multiple Categories.
  25. • Preferred Kind of a part. The preferred kind of a part designates the data format which the editor running the part must use to 'ternalize the part's content.  The preferred kind is stored in kODPropPreferredKind property of the part's StorageUnit.  If the kODPropPreferredKind property does not exist, then the editor can presume that the preferred kind of the part is the valueType of the first Value in the Contents Property (kODPropContents) of the part's StorageUnit.
  26. •        'nmap' = namespace mapping resource.  Please see the Dynamic Binding recipe(s) for further detail on 'nmap's.
  27.  
  28. Standard Kinds
  29.     
  30. Standard kinds are those data formats which, either through an official decree or by some defacto means, have become widely used and accepted.  Here are some examples:
  31.  
  32. Industry Standard Kinds:    ASCII, TIFF, JPEG etc.
  33. Standard Mac Kinds:'TEXT',     'PICT', 'stxt' etc.
  34.  
  35. Supporting a Standard Kind has many advantages. 
  36.  
  37. It permits your part editor to support a large amount of the content already out there.   It permits users to read old documents with your part editor.  Users like being able to read their old documents with the latest software instead of worrying about finding that copy of Surfwriter 0.1 which is lost among decade old backup floppies.  
  38.  
  39. Supporting a standard kind means there is a greater chance that your editor can read parts created by other editors.  This enables users to share documents created by your part editor.
  40.  
  41. Note on supporting  Standard Mac Kinds:
  42. 1. Special EditorPlatformKinds 'nmap' resource.  There is a special EditorPlatformKinds 'nmap' resource which your editor needs to have to register the fact that it supports Standard Mac Kinds.  DO NOT include Standard Mac Kinds in your normal EditorKinds 'nmap' resource.
  43. 2.  At runtime, if you need to convert a Mac OSType such as 'TEXT' into an ISO Type, do the following:
  44.  
  45. Get the translation object from the session:
  46.  
  47. ODTranslation* translation = session->GetTranslation(ev);
  48.  
  49. Then, call the translation object to convert the Mac OSType, or what we call PlatformType (a platform neutral term) to an ISO Type:
  50.  
  51. ODValueType valueType = translation->GetISOTypeFromPlatformType('TEXT' , kODPlatformFileType);  
  52. // Note, use kODPlatformDataType instead of kODPlatformFileType if you're converting a SCRAP type from the clipboard as opposed to a FILE type from the filesystem.
  53.  
  54. Note: kODPlatformFileType is defined in StdDefs.xh.  Translation is defined in Translt.xh.  Session is defined in ODSessn.xh.
  55.  
  56.  
  57. Coding Required
  58.  
  59. In order to correctly support multiple kinds, there are a handful of methods in part api where your editor needs to make sure it behaves properly.
  60.  
  61.         InitPart
  62. This method is    called when stationery is created, or when a user uses a tool from a tool palette to create a part in a container part.  Your editor should make sure it does the following:
  63.             1. Set the preferred Kind - write the appropriate ISO string into the kODPropPreferredKind property of your part.
  64.             2. Create a value whose type is that kind in the contents property
  65.             3. Initialize the content value with valid initial contents. Often leaving the value empty is a valid; it depends on the particular data format.
  66. Alternatively, perhaps as an optimization, your editor may just set an internal dirty flag, and then perform the above three steps in its Externalize method when it realizes there is no contents property.
  67.  
  68.         InitPartFromStorage
  69. This method is    called when a part is read back in.  This happens whenever a user opens a document or creates a new document.  Your editor should make sure it does the following:
  70.          1.    If you support any PlatformKinds (file), then you should first check for the HFSFlavor valueType in the contents property.  If it is there, then you have been bound to an empty storageUnit which is pointing to a file which you should use to internalize from.  This can happen in one of two ways, the user may have drag & dropped a traditional Macintosh File onto an OpenDoc document and your part editor was bound to the drop, or the user may have opened atraditional Macintosh File  with the OpenDoc™ launcher application.  For the real detailed info on how to make this work, please see the "Drag and Drop Recipes" recipe document, specifically the section titled "Incorporating data from a non-OpenDoc document".
  71.          2. Get the preferred kind - read the value from the kODPropPreferredKind property of your part.  If no property exists, then use the ValueType of the first value of the contents property as the preferred kind.  Keep the preferred kind in a field.
  72.          3. Focus your part's storageunit to the value of the contents property whose valuetype is the preferred kind.
  73.             4. Read the contents of that first value and create the in-memory data structures necessary to represent that content.
  74. Note: It is possible that your editor was bound to a part which previously had a different editor.  In this case, the Binding subsystem will automatically notify the user.  In this case, if your editor does not support the preferred kind, then use the highest fidelity kind in the contents property which your editor does support as the defacto preferred kind.  DO NOT update the preferred kind property until Externalize or ChangeKind is called on your part.
  75.  
  76.  
  77.         Externalize
  78. This method may be called at any time.  Depending on the "Save" model of the current document, and the idletime optimizations which may or may not be present, your part may be told to Externalize only when the user Saves a document, or as often as every minute.  The point is, don't assume that when you're told to Externalize, that it is for any one particular reason.  As an optimization, your editor should probably keep an fDirty flag which is set whenever the user changes the part's content, and cleared whenever Extenalization is completed.  If your fDirty flag is clear then your Externalize method should be a NOP.
  79. Your editor should make sure it does the following:
  80.    1.  Clean up the storage unit.  You need to prepare the storage unit for clean externalization from your part editor.  You should only have to do this the first time Externalize is called on your part whenever it is brought into memory.  Remove any values which you won't be updating.  Specifically, this means remove any values which have valueTypes/Kinds which your editor does not support, or are of lower fidelity than Kinds which you wish externalize.
  81.    2. Add values if necessary. Use AddValue to create or recreate the valueTypes you wish to externalize in proper fidelity order (first value - highest fidelity to last value - lowest fidelity).  Fidelity Ordering is important, because OpenDoc Binding and Translation use the ordering of the values in the Contents property to determine which value is probably of the highest fidelity to determine which editor would best edit any given part.
  82. These first two steps are called 'prepping your storage unit';  there will be examples in other methods where you need to 'reprep' your storage unit.
  83.             3. Externalize your content in the format of the preferred kind which your editor kept track of in a local field.
  84.                   DO NOT write some other Kind instead; that would be implicit translation, or translating formats behind the user's back.  It is usually not a good idea to change things behind the user's back.  Some applications behave this way today.  The application claims to read/write a particular data format, but when a document of that kind is opened with that application, the application converts the document to its own proprietary format when you save.  This is really annoying to the user, who is left wondering why can't their documents be more stable, and stick with the format they were created with.  In today's applications, this unexpected format change is also often associated with resetting of the document's name to "Untitled x" or "FooDocument - converted".  In OpenDoc, parts do not have any control over the name of the document, so this errant behaviour is automatically prevented.  The name of the document, just like the preferred kind of a part, should be considered a user setting.  Editors should not tamper with user settings.
  85.                There are ways for a user to explicitly change the preferred kind of a part.  These will be discussed later.  For now keep in mind that only the user should be changing the preferred kind of a part, and only then through an explicit action. 
  86.             4. OPTIONAL: Write out alternative Kinds.  As discussed above, your editor may want to write out one or more kinds in addition to the preferred kind.  The typical part editor should by default only write out either the one preferred kind, or the preferred kind, and one interchange (or standard) kind.  If you want your editor to write out many more representations than that, we recommend that the editor present a user interface in their settings or preferences dialog to allow the user to pick a set of kinds which your editor externalizes by default.
  87.                  
  88.         ExternalizeKinds
  89. This method is    called when the user does a Save A Copy… as multiple formats, or when a data interchange utility goes through a document asking all the parts to externalize themselves in a set of kinds extracted from a set of standard interchange kinds.
  90. Your editor should make sure it does the following:
  91.             1. Externalize the set of Kinds specified.  Make sure that the fidelity ordering of the values in your contents property is maintained by creating the values for these kinds in the right order.  You may need to reprep your contents property and recreate the values in order to make sure they are in the appropriate fidelity ordering.  Be sure to write out these kinds in addition to the preferred kind, NOT instead of the preferred kind.
  92.             2. Ignore unsupported kinds. Ignore any kinds in the set which you do not support.
  93.  
  94.         ChangeKind
  95. This method is    called when the user changes the preferred kind of a part.  This is usually done from the Part/Document Info dialog, although don't assume that will be the only user interface which can cause this method to be called.
  96. Your editor should make sure it does the following:
  97.             1. Externalize the Part in the given Kind.  Make sure that the fidelity ordering of the values in your contents property is maintained by creating the values for these kinds in the right order.  You may need to reprep your contents property and recreate the values in order to make sure they are in the appropriate fidelity ordering.  It is up to your part editor whether you keep the previous preferred kind or not.
  98.             2. Set that Kind to be the preferred Kind.   Write the given Kind into the preferred Kind property of the part.
  99.  
  100.         CloneTo
  101. This method is    similar to Externalize.  It is usually called in response to a data interchange action such as using the clipboard or drag-and-drop.  Please see the "Data Interchange Basics" recipe documents for precise detail about implementing the CloneTo method.  For the purposes of the multiple kind support however, make sure your editor does the following:
  102.             1. Write the same Kinds you if you were Externalizing plus any standard kinds you support.
  103.                 It is more important to write out standard kinds during CloneTo than Externalize because when your CloneTo method is called, it is more likely that your part is in the middle of a data interchange operation, and should therefore be trying extra hard to enable the user to move content to a different editor or application.
  104.             2. SetPromiseValue for each Kind if you are using promises.
  105.  
  106. Resources Required
  107.  
  108. 'nmap' resources are used to tell OpenDoc which kinds your editor supports.
  109. Your editor needs to list every kind it supports in its EditorKinds 'nmap' resource.
  110. It should also list which categories those Kinds belong to using KindCategories 'nmap's, the kind user strings using  KindUserstring 'nmap's, and the category userstrings using the CategoryUserstring 'nmap's.  See the Dynamic Binding recipe(s) for details on how to construct proper 'nmap' resources.
  111.  
  112. Multiple Kinds User Interface Description
  113.  
  114. Earlier we stated that the user should be the only thing which changes the preferred kind of a part. Here is how they do it. To change the preferred kind of an embedded part, the user does the following:
  115.         1. Select the part
  116.   2. Choose "Part Info" from the "Edit" menu.
  117.   3.    Change the Kind popup to reflect a new preferred kind
  118.         4. Optionally Change the Editor; some editors work better than others when it comes to certain kinds.
  119.   5. Click "OK"
  120.  
  121. To change the preferred kind of the root part / document, the user does the following:
  122.   1. Choose "Document Info" from the "Document" menu.
  123.   2.    Change the Kind popup to reflect a new preferred kind
  124.         3. Optionally Change the Editor; some editors work better than others when it comes to certain kinds.
  125.   4. Click "OK"
  126.  
  127. In any discussion of preferred kinds, it makes sense to also describe preferred Editors.  Using the Editor Setup Control Panel, the user can set a particular editor to be the preferred Editor for a particular Kind.  Whenever the user encounters a part of that kind, whose previous editor is unavailable, the user set preferred Editor for that kind is used to run that part.  Similarly, the user can set a particular editor to be the preferred Editor for a whole category, such as "Other Plain Text".    This means that whenever the user encounters a part whose kind is in the "Plain Text" category, whose previous editor is unavailable, and there is no preferred Editor for that kind, the user set preferred Editor for that category ("Plain Text") is used.